Photo by Michael on iPhone
秋天時期,冰川融化差不多了🧊
整理在 UIKit MVVM 架構下,頁面與頁面之間怎麼傳值,
UIKit 有這些實作招式
class CustomViewController: UIViewController, CustomViewModelDelegate {
@IBOutlet weak var titleLabel: UILabel!
var viewModel: CustomViewModel
required init?(coder: NSCoder) {
self.viewModel = CustomViewModel()
super.init(coder: coder)
}
override func viewDidLoad() {
super.viewDidLoad()
self.viewModel.delegate = self
}
func updateTitle(title: String) {
self.titleLabel.text = title
}
}
protocol CustomViewModelDelegate: AnyObject {
func updateTitle(title: String)
}
class CustomViewModel {
weak var delegate: CustomViewModelDelegate?
}
// MARK: - Interface Methods
extension CustomViewModel {
func updateTitleAction(title: String) {
delegate?.updateTitle(title: title)
}
}
extension Notification.Name {
enum settings {
static let domainExpansion = NSNotification.Name("domainExpansion")
static let 黑閃 = NSNotification.Name("黑閃")
}
}
struct SettingsView: View {
@State private var domainExpansion: String = "No Domain Expansion Yet"
var body: some View {
VStack {
Text(domainExpansion)
.onReceive(NotificationCenter.default.publisher(for: .settings.domainExpansion)) { (output) in
if let newDomainExpansion = output.object as? String {
self.domainExpansion = newDomainExpansion
}
}
}
}
}
Other 頁面
Button(action: {
NotificationCenter.default.post(name: .settings.domainExpansion, object: "簡易領域")
}) {
Text("🫸🏻🫷🏻")
}
Tips :
在 SwiftUI 中,你沒有像 UIKit 中的 viewDidLoad
、viewWillAppear
或 deinit
這樣的生命週期方法。所以,你不能像在 UIKit 中那樣在 deinit
中調用 NotificationCenter.default.removeObserver(self)
。
不過,當使用 NotificationCenter
的 publisher(for:name:object:)
方法與 SwiftUI 的 onReceive
結合時,你實際上不需要手動移除觀察者。當 View
被釋放或消失時,系統會自動處理這些訂閱和取消訂閱。
class CustomViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
viewModel.isViewVisibleChanged = { [weak self] in
self?.refreshActionButton()
}
}
func refreshActionButton() {
}
}
class CustomViewModel {
var isViewVisibleChanged: (() -> Void)?
var isViewVisible: Bool = false {
didSet {
isViewVisibleChanged?()
}
}
}
// MARK: - Private Methods
extension CustomViewModel {
func change() {
DispatchQueue.main.async {
self.isViewVisible = true
}
}
}
Objective-C 的產物,所以不特別實作。
Key-Value Observing(KVO)是一種 Objective-C 編程模式,允許一個物件觀察另一物件的屬性的變化。它主要基於 Objective-C 的動態性質。在 Swift 中使用 KVO 有一些要求和考慮事項,但它仍然可以與 NSObject
的子類一起使用。
使用 KVO 的基本步驟是:
NSObject
。@objc dynamic
修飾,以確保它們是動態的。addObserver(_:forKeyPath:options:context:)
方法註冊它要觀察的屬性。observeValue(forKeyPath:of:change:context:)
方法會被呼叫。removeObserver(_:forKeyPath:)
來停止觀察。以下是一個簡單的範例:
import Foundation
class Person: NSObject {
@objc dynamic var name: String = ""
}
class Observer: NSObject {
var person: Person
var observation: NSKeyValueObservation?
init(person: Person) {
self.person = person
super.init()
observation = person.observe(\\.name, options: [.new], changeHandler: { (object, change) in
if let newValue = change.newValue {
print("Name changed to \\(newValue)")
}
})
}
}
let person = Person()
let observer = Observer(person: person)
person.name = "John"
// 輸出: "Name changed to John"
person.name = "Jane"
// 輸出: "Name changed to Jane"
雖然 KVO 在 Objective-C 中很受歡迎,但在 Swift 中,很多人傾向於使用其他模式,例如 Delegate、Closure 或 Combine Framework,因為它們提供了更加 Swift 式的語法和功能。
下次介紹 Swift 新的傳值框架